package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.commons.templates.FaceTemplate;
import com.tanhua.commons.templates.HuanXinTemplate;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.commons.templates.SmsTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.vo.ErrorResult;
import com.tanhua.domain.vo.UserInfoVo;
import com.tanhua.dubbo.api.db.UserApi;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.RecommendUserApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.GetAgeUtil;
import com.tanhua.server.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 业务逻辑处理类
 */
@Service
@Slf4j//日志注解
public class UserService {
    @Reference
    private UserApi userApi;

    @Reference
    private UserInfoApi userInfoApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private SmsTemplate smsTemplate;

    @Value("${tanhua.redisValidateCodeKeyPrefix}")
    private String redisValidateCodeKey;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private FaceTemplate faceTemplate;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Reference
    private RecommendUserApi recommendUserApi;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    
    /**
     * 保存用户返回userId
     *
     * @param user
     * @return
     */
    public Long saveUser(User user) {
        return userApi.saveUser(user);
    }

    /**
     * 根据手机号码查询用户对象
     *
     * @param mobile
     * @return
     */
    public User findByMobile(String mobile) {
        return userApi.queryByMobile(mobile);
    }

    /**
     * 登录第一步---获取验证码
     */
    public void sendValidCode(String mobile) {
        //a.根据手机号判断redis中验证码是否失效
        //redisTemplate.boundValueOps()
        String redisCode = redisTemplate.opsForValue().get(redisValidateCodeKey + mobile);
        //b.如果redis有未失效的验证码，提示用户
        if (!StringUtils.isEmpty(redisCode)) {
            throw new TanHuaException(ErrorResult.duplicate());
        }
        //c.如果没有未失效的验证码，生成验证码调用短信接口发送验证码
        String validCode = "123456";//RandomStringUtils.randomNumeric(6);
        //永远不执行 为了省5分钱
        log.debug("手机号码{}，验证码{}", mobile, validCode);
        if (false) {
            Map<String, String> stringStringMap = smsTemplate.sendValidateCode(mobile, validCode);
            if (stringStringMap != null) {
                throw new TanHuaException(ErrorResult.error());
            }
        }
        //d.将验证码存入redis
        redisTemplate.opsForValue().set(redisValidateCodeKey + mobile, validCode, 5, TimeUnit.MINUTES);
        log.debug("验证码发送成功了。。。");
    }

    /**
     * 登录第二步---注册登录
     */
    public Map loginReg(String mobile, String code) {
        String type = "0101";// 0101为登录，0102为注册
        //定义返回的结果对象
        Map map = new HashMap();
        boolean isNew = false;//false:非新用户 true:新用户
        //a.根据手机号查询redis验证是否存在
        String redisCode = redisTemplate.opsForValue().get(redisValidateCodeKey + mobile);
        //b.验证码不存在，告知用户验证码失效
        if (StringUtils.isEmpty(redisCode)) {
            throw new TanHuaException(ErrorResult.loginError());
        }
        //c.验证码存在，校验验证码
        if (!redisCode.equals(code)) {
            throw new TanHuaException(ErrorResult.validateCodeError());
        }
        //d.根据手机号查询用户是否存在
        User user = userApi.queryByMobile(mobile);
        //e.用户不存在，自动注册
        if (user == null) {
            user = new User();
            user.setMobile(mobile);//手机号
            Long userId = userApi.saveUser(user); //注册用户后可以获取用户id
            user.setId(userId);//设置下userId
            isNew = true;
            log.debug("用户注册了手机号{} userId是{}", mobile, userId);
            huanXinTemplate.register(userId);//解耦 异步处理（MQ）
            log.debug("环信云注册成功了....手机号{},userId{}", mobile, userId);
            type = "0102";//注册
        }
        //f.用户存在
        //g.生成token存入redis(登录-解决之前cookie+session)
        String token = jwtUtils.createJWT(mobile, user.getId());
        String userStr = JSON.toJSONString(user);
        //key:token value:用户对象-字符串  设置1天有效
        redisTemplate.opsForValue().set("TOKEN_" + token, userStr, 1, TimeUnit.DAYS);
        map.put("token", token);
        map.put("isNew", isNew);
        //j.验证码删除
        redisTemplate.delete(redisValidateCodeKey + mobile);
        log.debug("用户登录成功了。。。token:{},isNew{}", token, isNew);
        //构造日志消息
        Map message = new HashMap();
        message.put("userId",user.getId().toString());
        message.put("type",type);
        message.put("logtime",new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        rocketMQTemplate.convertAndSend("tanhua-logs",message);
        return map;
    }

    /**
     * 设置头像-保存用户基础信息
     */
    public void loginReginfo(UserInfoVo userInfoVo) {
        //a.根据请求头的token从redis查询user对象获取userId
        Long userId = UserHolder.getUserId();//用户id
        //b.封装UserInfo调用服务保存用户基本信息
        UserInfo userInfo = new UserInfo();
        //BeanUtils可以通过此工具类将a对象属性值 copy 到b对象相同的属性上
        //如果属性不一样 手动设置下即可
        BeanUtils.copyProperties(userInfoVo, userInfo);
        userInfo.setId(userId);//用户id
        //设置年龄
        if(!StringUtils.isEmpty(userInfoVo.getBirthday())){
            userInfo.setAge(GetAgeUtil.getAge(userInfoVo.getBirthday()));
        }
        userInfoApi.saveUserInfo(userInfo);
    }

    /**
     * 拍照-人脸识别上传头像
     *
     * @param headPhoto
     */
    public void loginReginfoHead(MultipartFile headPhoto) {
        try {
            Long userId = UserHolder.getUserId();//用户id
            //b.调用人脸识别组件  成功：继续往下 失败：返回错误信息
            boolean flag = faceTemplate.detect(headPhoto.getBytes());
            log.debug("************人脸识别结果:{}************",flag);
            if (!flag) {
                throw new TanHuaException(ErrorResult.faceError());
            }
            //c.调用上传头像组件 成功：继续往下 失败：返回错误信息
            //headUrl:返回的上传到oss的头像地址
            String headUrl = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
            log.debug("************headUrl:{}************",headUrl);
            //d.调用服务 跟用户id更新用户头像
            UserInfo userInfo = new UserInfo();
            userInfo.setId(userId);//用户id
            userInfo.setAvatar(headUrl);//用户头像
            userInfoApi.updateUserInfo(userInfo);
            log.debug("************人脸识别上传头像成功了，用户id{}************",userId);
        } catch (Exception e) {
            //系统繁忙，稍后再试
            throw new TanHuaException(ErrorResult.error());
        }

    }

    /**
     * 根据token获取user对象
     * @param token
     * @return
     */
    public User getUserByToken(String token) {
        //a.根据请求头的token从redis查询user对象获取userId
        String userStr = redisTemplate.opsForValue().get("TOKEN_" + token);
        if (StringUtils.isEmpty(userStr)) {
            return null;
        }
        redisTemplate.expire("TOKEN_" + token,1,TimeUnit.DAYS);
        //将userStr转为User对象
        return JSON.parseObject(userStr, User.class);
    }



}
